<template>
  <template v-if="props.isOperator">
    <el-button type="primary" class="operator-header" @click="addNode">添加节点</el-button>
    <el-button type="danger" class="operator-header" @click="removeNode">删除节点</el-button>
  </template>
  <el-tree
    v-bind="$attrs"
    ref="treeRef"
    class="tree"
    :indent="0"
    node-key="id"
    :data="props.treeData"
    :props="props.defaultProps"
    :check-strictly="props.checkStrictly"
    :show-checkbox="props.isShowCheckbox"
    :check-on-click-node="props.checkOnClickNode"
    :default-expand-all="props.defaultExpandAll"
    :allow-drag="allowDrag"
    :draggable="props.isDraggable"
    :allow-drop="allowDrop"
    @node-drag-end="handleDragEnd"
    @node-click="handleNodeClick"
    @node-contextmenu="editNode"
    @check-change="getCheckedAllNodes"
  >
    <template #default="{ node }">
      <svg :name="checkIconByNodeLevel(node)" />
      <input
        v-if="showIpt && node.label === curNodLabel && isEditNode"
        ref="inputRef"
        type="text"
        :value="node.label"
        @blur="showIpt = false"
        @keyup.enter="updateNodeLabel($event, node)"
      />
      <span v-else>
        <el-tooltip
          v-if="node.label.length > ellipsisLen"
          :content="node.label"
          placement="right"
        >
          <span :class="compNodeCustomized(node)">
            {{ ellipsis(node.label, ellipsisLen) }}
          </span>
        </el-tooltip>
        <span v-else :class="compNodeCustomized(node)">
          {{ node.label }}
        </span>
      </span>
    </template>
  </el-tree>
</template>

<!-- <script setup lang="ts">
    export default {
        name: 'homeView'
    }
</script> -->
<!-- <script setup lang="ts" name="GTree"> -->
<script lang="ts">
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { defineComponent, defineExpose, nextTick, ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import type Node from 'element-plus/es/components/tree/src/model/node'
import props  from './props'

export default defineComponent({
  name: 'GTree',
  props: props,
  emits: ['eCurNode', 'eCheckedNodes', 'eSaveNodes', 'showOptDialogFunc' ],
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  setup(props, { attrs, emit, expose }) {
    const showIpt = ref<boolean>(false) // 是否显示输入框
    const curNodLabel = ref<string>() // 记录右键点击的节点
    const inputRef = ref() // 输入框实例
    const treeRef = ref() // 树实例

    // 判断节点能否被放置 如果返回 false ，节点不能被放置
    const allowDrop = () => true
    // 判断节点能否被拖拽 如果返回 false ，节点不能被拖动
    const allowDrag = () => true

    const ellipsis = (value: string, len: number) => {
      if (!value) return ''
      if (value.length > len) return value.slice(0, len) + '...'
    }

    // 点击节点时触发
    // eslint-disable-next-line no-undef
    const handleNodeClick = (data: Tree, node: { data: { disabled: boolean; }; checked: boolean; }) => {
      emit('eCurNode', data)
      // 点击该行 如果有复选框并且没被禁用  即选中复选框
      if (!props.isShowCheckbox || node.data.disabled) return
      node.checked = !node.checked
    }
    // 删除节点
    const removeNode = () => {
      const checkedNodes = treeRef.value.getCheckedNodes()
      if (checkedNodes.length === 0)
        return ElMessage.warning({ message: '请至少勾选一项才能删除节点', grouping: true, showClose: true })
      for (const node of checkedNodes) {
        nextTick(() => {
          treeRef.value.remove(node.id, false)
        })
      }
    }

    // 右击节点时触发
    const editNode = (event: MouseEvent, node: Node) => {
      event.preventDefault()
      curNodLabel.value = node.label
      showIpt.value = true
      nextTick(() => {
        inputRef.value.focus()
      })
    }

    // 更新节点的label
    // eslint-disable-next-line no-undef
    const updateNodeLabel = (e: Event, node: Tree) => {
      const target = e.target as HTMLInputElement
      if (isValueInTree(props.treeData, target.value)) return alert('该节点已存在')
      node = Object.assign({}, node)
      node.data.label = target.value
      showIpt.value = false
    }

    // 使用非递归方式查找树中是否存在某个值
    function isValueInTree(data: string | any[], value: string) {
      const stack = [...data]
      while (stack.length) {
        const node = stack.pop()
        if (node.label === value) return true
        if (Array.isArray(node.children)) {
          stack.push(...node.children)
        }
      }
      return false
    }

    // 新增节点
    const addNode = () => {
      const checkedNodes = treeRef.value.getCheckedNodes()
      if (checkedNodes.length === 0)
        return ElMessage.warning({ message: '请至少勾选一项才能添加节点', grouping: true, showClose: true })
      emit('showOptDialogFunc')
      return
      const nodeName = prompt('请输入节点名称')
      if (!nodeName) return

      if (isValueInTree(props.treeData, nodeName))
        return ElMessage.warning({ message: '该节点已存在', grouping: true, showClose: true })
      for (const parentNode of checkedNodes) {
        const newNode = {
          id: props.treeData.length + 1,
          label: nodeName
        }
        if (!parentNode.children) {
          parentNode.children = []
        }
        parentNode.children.push(newNode)
      }
    }

    // 结束拖拽
    const handleDragEnd = (dropNode: Node) => {
      if (!dropNode) return
      if (props.isDraggable === false) return
      saveNode()
    }

    // 保存节点
    function saveNode() {
      emit('eSaveNodes', props.treeData)
    }

    // 复选框改变
    // eslint-disable-next-line no-undef
    const getCheckedAllNodes = (data: Tree, isSelected: boolean) => {
      if (!props.isShowCheckbox) return
      const checkedNodes = treeRef.value.getCheckedNodes()
      const halfCheckedNodes = treeRef.value.getHalfCheckedNodes()
      // data: 当前节点的数据
      // isSelected: 当前节点是否被选中
      // checkedNodes: 所有选中的节点
      // halfCheckedNodes: 所有半选中的节点
      emit('eCheckedNodes', data, isSelected, checkedNodes, halfCheckedNodes)
    }

    // 根据节点层级显示不同的图标
    const checkIconByNodeLevel = computed(() => {
      return (node: { childNodes: []; expanded: boolean; }) => {
        if (node.childNodes.length === 0) return 'ant-FileOutlined'
        return node.expanded ? 'ant-FolderOpenOutlined' : 'ant-MinusSquareOutlined'
      }
    })

    // 根据id || disabled 控制节点颜色变化
    const compNodeCustomized = computed(() => {
      // const customizedIds = [1]; // 指定需要自定义的节点id数组

      return (node: { data: { id: number; disabled: boolean; }; }) => {
        if (node.data.disabled) return 'node-customized'
        // return customizedIds.includes(node.data.id) ? 'node-customized' : '';
      }
    })
    expose({ treeRef: treeRef, removeNode: removeNode, addNode: addNode })
    return {
      props,
      showIpt,
      curNodLabel,
      inputRef,
      treeRef,
      allowDrop,
      allowDrag,
      ellipsis,
      handleNodeClick,
      removeNode,
      editNode,
      updateNodeLabel,
      isValueInTree,
      addNode,
      handleDragEnd,
      saveNode,
      getCheckedAllNodes,
      checkIconByNodeLevel,
      compNodeCustomized
    }
  }
})
</script>

<style lang="scss" scoped>
.tree {
	width: 100%;
	height: 100%;
	padding-bottom: 10px;
	overflow-x: hidden;
	overflow-y: auto;
	:deep(.el-tree-node) {
		position: relative;
	}
	:deep(.el-tree-node__children) {
		padding-left: 16px;
	}
	:deep(.el-tree-node::before) {
		content: '';
		width: 22px;
		height: 20px;
		position: absolute;
		left: -12px;
		top: 1px;
		border-width: 1px;
		border-left: 1px dashed #ccc;
	}
	:deep(.el-tree-node:last-child::before) {
		height: 38px;
	}
	:deep(.el-tree-node::after) {
		content: '';
		width: 22px;
		height: 20px;
		position: absolute;
		left: -3px;
		top: 11px;
		border-width: 1px;
		border-top: 1px dashed #ccc;
	}
	& > :deep(.el-tree-node::after) {
		border-top: none;
	}
	& > :deep(.el-tree-node::before) {
		border-left: none;
	}
	:deep(.el-tree-node__expand-icon) {
		font-size: 16px;
		:deep(&.is-leaf) {
			color: transparent;
			display: none;
		}
	}
	.node-customized {
		color: #c4bbb3;
	}
	// 一级不显示复选框其余内层都显示
	// :deep(.el-checkbox .el-checkbox__inner) {
	// 	display: none;
	// }

	// :deep(div[role='group']) {
	// 	.el-checkbox .el-checkbox__inner {
	// 		display: inline-block;
	// 	}
	// }

	// :deep(.el-tree-node__content) {
	// 	:deep(.el-checkbox .el-checkbox__inner) {
	// 		display: none;
	// 	}
	// }

	// 只有最后一级显示复选框
	// :deep(.el-tree-node) {
	// 	.is-leaf + .el-checkbox .el-checkbox__inner {
	// 		display: inline-block;
	// 	}
	// 	.el-checkbox .el-checkbox__inner {
	// 		display: none;
	// 	}
	// }
	/* 隐藏所有复选框
	-----------------------------------------------------------*/
	// :deep(.el-checkbox .el-checkbox__inner) {
	// 	display: none;
	// }

	/* 只在三级菜单中显示复选框
	-----------------------------------------------------------*/
	// :deep(div[role='group'] div[role='group'] .el-checkbox .el-checkbox__inner) {
	// 	display: inline-block;
	// }\
    .operator-header {
        margin-bottom: 20px;
    }
}
</style>
